package com.zijidelu.luframework.utils.lang.reflect.generic;

import cn.hutool.core.map.reference.WeakKeyValueConcurrentMap;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 泛型解析工具类
 * <p>
 * 提供Java泛型类型的解析、查询和格式化功能，支持：
 * <ul>
 *   <li>解析类和接口的泛型参数</li>
 *   <li>处理复杂的泛型继承关系</li>
 *   <li>格式化泛型类型信息</li>
 * </ul>
 *
 * @author zijidelu
 * @datetime 2025/10/18 23:00
 */
public final class GenericResolveUtil {
    // ==================== 缓存机制 ====================

    /**
     * 泛型解析结果缓存
     * Key: 源类
     * Value: 另一个Map，其Key是目标类，Value是解析出的泛型参数列表
     */
    private static final Map<Class<?>, Map<Class<?>, List<Type>>> GENERIC_CACHE = new WeakKeyValueConcurrentMap<>();

    // ==================== 核心解析方法 ====================

    /**
     * 解析目标类型的泛型参数（带缓存）
     * <p>
     * 此方法是 {@link #resolveGenerics(Class, Class)} 的缓存版本。
     * 对于相同的 sourceClass 和 targetType 组合，解析结果会被缓存，
     * 后续调用将直接返回缓存结果，避免重复计算，提升性能。
     *
     * @param sourceClass 源类，不能为null
     * @param targetType  目标类型（类或接口），不能为null
     * @return 目标类型的泛型参数列表，如果未找到则返回空列表
     * @throws NullPointerException 如果任一参数为null
     */
    public static List<Type> resolveGenericsWithCache(Class<?> sourceClass, Class<?> targetType) {
        Objects.requireNonNull(sourceClass, "Source class cannot be null");
        Objects.requireNonNull(targetType, "Target type cannot be null");

        // 1. 尝试从一级缓存（源类）中获取
        Map<Class<?>, List<Type>> cacheForSource = GENERIC_CACHE.get(sourceClass);
        if (cacheForSource != null) {
            // 2. 尝试从二级缓存（目标类）中获取结果
            List<Type> cachedResult = cacheForSource.get(targetType);
            if (cachedResult != null) {
                return cachedResult;
            }
        }

        // 3. 缓存未命中，调用原始方法进行计算
        List<Type> result = resolveGenerics(sourceClass, targetType);

        // 4. 将计算结果存入缓存
        // 使用 computeIfAbsent 可以原子性地完成“获取或创建”操作，更简洁且线程安全
        Map<Class<?>, List<Type>> finalCacheForSource = GENERIC_CACHE.computeIfAbsent(
                sourceClass,
                k -> new ConcurrentHashMap<>()
        );
        finalCacheForSource.put(targetType, result);

        return result;
    }

    /**
     * 解析目标类型的泛型参数
     * <p>
     * 支持解析类继承和接口实现中的泛型参数，会遍历整个类层次结构
     * 直到找到匹配的目标类型。
     *
     * @param sourceClass 源类，不能为null
     * @param targetType  目标类型（类或接口），不能为null
     * @return 目标类型的泛型参数列表，如果未找到则返回空列表
     * @throws NullPointerException 如果任一参数为null
     */
    public static List<Type> resolveGenerics(Class<?> sourceClass, Class<?> targetType) {
        Objects.requireNonNull(sourceClass, "Source class cannot be null");
        Objects.requireNonNull(targetType, "Target type cannot be null");

        // 尝试从类继承中解析
        Optional<Type> classType = findInClassHierarchy(sourceClass, targetType);
        if (classType.isPresent()) {
            // 构建类型变量映射表
            Map<String, Type> typeMap = buildTypeVariableMap(sourceClass);
            return extractGenericArguments(classType.get(), typeMap);
        }

        // 尝试从接口实现中解析
        Optional<Type> interfaceType = findInInterfaces(sourceClass, targetType);
        if (interfaceType.isPresent()) {
            // 构建类型变量映射表
            Map<String, Type> typeMap = buildTypeVariableMap(sourceClass);
            return extractGenericArguments(interfaceType.get(), typeMap);
        }

        return Collections.emptyList();
    }

    /**
     * 解析目标类型指定位置的泛型参数
     *
     * @param sourceClass 源类
     * @param targetType  目标类型
     * @param paramIndex  泛型参数索引（从0开始）
     * @return 指定位置的泛型参数，如果索引越界则返回Optional.empty()
     */
    public static Optional<Type> resolveGenericParam(Class<?> sourceClass, Class<?> targetType, int paramIndex) {
        List<Type> generics = resolveGenerics(sourceClass, targetType);

        if (paramIndex >= 0 && paramIndex < generics.size()) {
            return Optional.of(generics.get(paramIndex));
        }

        return Optional.empty();
    }

    // ==================== 查找方法 ====================

    /**
     * 在类继承层次中查找目标类型
     * <p>
     * 支持查找任意层级的父类，包括爷爷类、祖宗类等所有上层继承关系。
     * 例如：class D extends C，class C extends B，class B extends A<T>，
     * 可以从 D 查找到 A 的泛型信息。
     *
     * @param subclass   起始子类
     * @param targetType 目标父类
     * @return 找到的类型信息，包装在Optional中
     */
    public static Optional<Type> findInClassHierarchy(Class<?> subclass, Class<?> targetType) {
        // 沿着继承链向上查找
        Class<?> current = subclass;

        while (current != null && !current.equals(Object.class)) {
            // 检查当前类是否是目标类型
            if (targetType.equals(current)) {
                // 需要找到从 subclass 到 current 的泛型路径
                return findGenericPath(subclass, current);
            }

            current = current.getSuperclass();
        }

        return Optional.empty();
    }

    /**
     * 在接口实现中查找目标接口
     * <p>
     * 支持查找任意层级的接口，包括：
     * <ul>
     *   <li>当前类直接实现的接口</li>
     *   <li>父类实现的接口</li>
     *   <li>接口的父接口（继承的接口）</li>
     * </ul>
     * 例如：class C implements B，interface B extends A<T>，
     * 可以从 C 查找到 A 的泛型信息。
     *
     * @param clazz           起始类
     * @param targetInterface 目标接口
     * @return 找到的接口类型信息，包装在Optional中
     */
    public static Optional<Type> findInInterfaces(Class<?> clazz, Class<?> targetInterface) {
        // 使用 traverseClassHierarchy 遍历整个类层次结构
        // 这会包括当前类、所有父类，以及它们实现的所有接口
        return traverseClassHierarchy(clazz, currentClass -> {
            // 检查当前类实现的接口
            for (Type genericInterface : currentClass.getGenericInterfaces()) {
                Optional<Type> found = findInterfaceInType(genericInterface, targetInterface, clazz);
                if (found.isPresent()) {
                    return found;
                }
            }
            return Optional.empty();
        });
    }

    /**
     * 在类型中查找目标接口（支持接口继承）
     *
     * @param type            当前类型（可能是接口）
     * @param targetInterface 目标接口
     * @param sourceClass     源类（用于构建类型映射）
     * @return 找到的接口类型信息
     */
    private static Optional<Type> findInterfaceInType(Type type, Class<?> targetInterface, Class<?> sourceClass) {
        Class<?> rawType = getRawType(type);

        // 直接匹配
        if (targetInterface.equals(rawType)) {
            return Optional.of(type);
        }

        // 检查是否是接口的父接口
        if (rawType.isInterface()) {
            // 递归查找这个接口继承的接口
            for (Type superInterface : rawType.getGenericInterfaces()) {
                Optional<Type> found = findInterfaceInType(superInterface, targetInterface, sourceClass);
                if (found.isPresent()) {
                    return found;
                }
            }
        }

        return Optional.empty();
    }

    /**
     * 查找从源类到目标类的泛型路径
     * <p>
     * 构建从源类到目标类的完整泛型信息，包括所有中间的类型变量映射。
     *
     * @param sourceClass 源类
     * @param targetClass 目标类
     * @return 泛型路径，如果找不到返回Optional.empty()
     */
    private static Optional<Type> findGenericPath(Class<?> sourceClass, Class<?> targetClass) {
        // 构建类型变量映射
        Map<String, Type> typeMap = new HashMap<>();
        Class<?> current = sourceClass;

        // 向上遍历继承链
        while (current != null && !current.equals(Object.class)) {
            Type genericSuperclass = current.getGenericSuperclass();

            if (genericSuperclass != null) {
                // 更新类型映射
                processGenericTypes(genericSuperclass, typeMap);

                Class<?> rawSuperclass = getRawType(genericSuperclass);

                // 检查是否到达目标类
                if (targetClass.equals(rawSuperclass)) {
                    // 使用类型映射解析泛型参数
                    Type resolvedType = resolveType(genericSuperclass, typeMap);
                    return Optional.of(resolvedType);
                }

                current = rawSuperclass;
            } else {
                current = current.getSuperclass();
            }
        }

        return Optional.empty();
    }

    // ==================== 类型解析辅助方法 ====================

    /**
     * 构建类型变量映射表
     * <p>
     * 遍历类层次结构，收集所有类型变量到实际类型的映射关系。
     * 例如：class A<T> extends B<String>，则建立 T -> String 的映射。
     *
     * @param clazz 起始类
     * @return 类型变量名到实际类型的映射
     */
    private static Map<String, Type> buildTypeVariableMap(Class<?> clazz) {
        Map<String, Type> typeMap = new HashMap<>();

        traverseClassHierarchy(clazz, currentClass -> {
            // 处理父类
            processGenericTypes(currentClass.getGenericSuperclass(), typeMap);

            // 处理接口
            for (Type interfaceType : currentClass.getGenericInterfaces()) {
                processGenericTypes(interfaceType, typeMap);
            }

            return true; // 继续遍历
        });

        return typeMap;
    }

    /**
     * 处理泛型类型，提取类型变量映射
     *
     * @param type    要处理的类型
     * @param typeMap 类型变量映射表
     */
    private static void processGenericTypes(Type type, Map<String, Type> typeMap) {
        if (type instanceof ParameterizedType parameterizedType) {
            Class<?> rawClass = getRawType(parameterizedType);
            TypeVariable<?>[] typeParameters = rawClass.getTypeParameters();
            Type[] actualArguments = parameterizedType.getActualTypeArguments();

            // 建立类型变量到实际参数的映射
            for (int i = 0; i < typeParameters.length && i < actualArguments.length; i++) {
                Type resolvedArg = resolveType(actualArguments[i], typeMap);
                typeMap.put(typeParameters[i].getName(), resolvedArg);
            }
        }
    }

    /**
     * 提取参数化类型的泛型参数
     *
     * @param type    参数化类型
     * @param typeMap 类型变量映射表
     * @return 解析后的泛型参数列表
     */
    private static List<Type> extractGenericArguments(Type type, Map<String, Type> typeMap) {
        if (type instanceof ParameterizedType parameterizedType) {
            return Arrays.stream(parameterizedType.getActualTypeArguments())
                    .map(arg -> resolveType(arg, typeMap))
                    .collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    /**
     * 递归解析类型
     * <p>
     * 支持解析：
     * <ul>
     *   <li>TypeVariable：使用映射表解析为实际类型</li>
     *   <li>ParameterizedType：递归解析其类型参数</li>
     *   <li>WildcardType：解析其上下界</li>
     *   <li>Class：直接返回</li>
     * </ul>
     *
     * @param type    要解析的类型
     * @param typeMap 类型变量映射表
     * @return 解析后的类型
     */
    private static Type resolveType(Type type, Map<String, Type> typeMap) {
        // 解析类型变量
        if (type instanceof TypeVariable<?> typeVariable) {
            return typeMap.getOrDefault(typeVariable.getName(), type);
        }

        // 解析参数化类型
        if (type instanceof ParameterizedType parameterizedType) {
            Type[] resolvedArgs = Arrays.stream(parameterizedType.getActualTypeArguments())
                    .map(arg -> resolveType(arg, typeMap))
                    .toArray(Type[]::new);

            return new ResolvedParameterizedType(
                    getRawType(parameterizedType),
                    resolvedArgs,
                    parameterizedType.getOwnerType());
        }

        // 解析通配符类型
        if (type instanceof WildcardType wildcardType) {
            Type[] upperBounds = resolveTypes(wildcardType.getUpperBounds(), typeMap);
            Type[] lowerBounds = resolveTypes(wildcardType.getLowerBounds(), typeMap);
            return new ResolvedWildcardType(upperBounds, lowerBounds);
        }

        // 普通类直接返回
        return type;
    }

    /**
     * 批量解析类型数组
     *
     * @param types   类型数组
     * @param typeMap 类型变量映射表
     * @return 解析后的类型数组
     */
    private static Type[] resolveTypes(Type[] types, Map<String, Type> typeMap) {
        return Arrays.stream(types)
                .map(type -> resolveType(type, typeMap))
                .toArray(Type[]::new);
    }

    // ==================== 工具方法 ====================

    /**
     * 获取类型的原始Class对象
     *
     * @param type 类型
     * @return 原始Class对象，对于无法确定的情况返回Object.class
     */
    public static Class<?> getRawType(Type type) {
        if (type instanceof Class<?> clazz) {
            return clazz;
        }
        if (type instanceof ParameterizedType parameterizedType) {
            return getRawType(parameterizedType.getRawType());
        }
        if (type instanceof TypeVariable<?> typeVariable) {
            Type[] bounds = typeVariable.getBounds();
            return bounds.length > 0 ? getRawType(bounds[0]) : Object.class;
        }
        return Object.class;
    }

    /**
     * 获取Type的原始类型（泛型版本）
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> getRawTypeGeneric(Type type) {
        return (Class<T>) getRawType(type);
    }

    /**
     * 遍历类层次结构
     * <p>
     * 使用深度优先搜索遍历类及其父类、接口，避免重复访问。
     *
     * @param startClass 起始类
     * @param processor  处理器函数，返回Optional表示是否找到目标
     * @param <T>        返回值类型
     * @return 处理器的返回值
     */
    private static <T> T traverseClassHierarchy(Class<?> startClass, Function<Class<?>, T> processor) {
        Set<Class<?>> visited = new HashSet<>();
        Deque<Class<?>> stack = new ArrayDeque<>();
        stack.push(startClass);

        while (!stack.isEmpty()) {
            Class<?> current = stack.pop();

            // 跳过null、Object类和已访问的类
            if (current == null || current.equals(Object.class) || visited.contains(current)) {
                continue;
            }
            visited.add(current);

            // 应用处理器
            T result = processor.apply(current);
            if (result instanceof Optional<?> optional && optional.isPresent()) {
                return result;
            }
            if (result != null && !(result instanceof Boolean)) {
                return result;
            }

            // 添加父类到栈
            Class<?> superClass = current.getSuperclass();
            if (superClass != null && !superClass.equals(Object.class)) {
                stack.push(superClass);
            }

            // 添加接口到栈
            for (Class<?> interfaceClass : current.getInterfaces()) {
                if (!interfaceClass.equals(Object.class)) {
                    stack.push(interfaceClass);
                }
            }
        }

        return null;
    }

    // ==================== 格式化方法 ====================

    /**
     * 格式化类型为易读的字符串
     *
     * @param type 类型
     * @return 格式化后的字符串
     */
    public static String formatType(Type type) {
        if (type instanceof Class<?> clazz) {
            return clazz.getSimpleName();
        }
        if (type instanceof ParameterizedType parameterizedType) {
            return formatParameterizedType(parameterizedType);
        }
        if (type instanceof TypeVariable<?> typeVariable) {
            return typeVariable.getName();
        }
        if (type instanceof WildcardType wildcardType) {
            return formatWildcardType(wildcardType);
        }
        return type.toString();
    }

    /**
     * 格式化参数化类型
     *
     * @param parameterizedType 参数化类型
     * @return 格式化字符串，如：List<String>
     */
    private static String formatParameterizedType(ParameterizedType parameterizedType) {
        String rawName = getRawType(parameterizedType).getSimpleName();
        String typeArgs = Arrays.stream(parameterizedType.getActualTypeArguments())
                .map(GenericResolveUtil::formatType)
                .collect(Collectors.joining(", "));
        return rawName + "<" + typeArgs + ">";
    }

    /**
     * 格式化通配符类型
     *
     * @param wildcardType 通配符类型
     * @return 格式化字符串，如：? extends Number 或 ? super String
     */
    private static String formatWildcardType(WildcardType wildcardType) {
        // 处理下界（? super）
        Type[] lowerBounds = wildcardType.getLowerBounds();
        if (lowerBounds.length > 0) {
            return "? super " + formatType(lowerBounds[0]);
        }

        // 处理上界（? extends）
        Type[] upperBounds = wildcardType.getUpperBounds();
        if (upperBounds.length > 0 && !upperBounds[0].equals(Object.class)) {
            return "? extends " + formatType(upperBounds[0]);
        }

        // 无限制通配符
        return "?";
    }

    /**
     * 格式化类型列表
     *
     * @param types 类型列表
     * @return 格式化字符串，如：[String, Integer]
     */
    public static String formatTypeList(List<Type> types) {
        return types.stream()
                .map(GenericResolveUtil::formatType)
                .collect(Collectors.joining(", ", "[", "]"));
    }

}
